package cn.iocoder.yudao.module.ym.job;

import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.framework.web.config.WebProperties;
import cn.iocoder.yudao.module.infra.dal.dataobject.job.JobDO;
import cn.iocoder.yudao.module.infra.dal.mysql.job.JobMapper;
import cn.iocoder.yudao.module.infra.enums.DictDataConstants;
import cn.iocoder.yudao.module.infra.enums.TicketLogRecordConstants;
import cn.iocoder.yudao.module.infra.enums.TicketStatusEnum;
import cn.iocoder.yudao.module.infra.enums.YmMessageEnum;
import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApiImpl;
import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.ym.dal.dataobject.ticket.TicketDO;
import cn.iocoder.yudao.module.ym.dal.dataobject.ticketlog.TicketLogDO;
import cn.iocoder.yudao.module.ym.dal.mysql.ticket.TicketMapper;
import cn.iocoder.yudao.module.ym.dal.mysql.ticketlog.TicketLogMapper;
import cn.iocoder.yudao.module.ym.service.site.SiteService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;

import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserNickname;

/**
 * 定时保养工单
 *
 * @author j-sentinel
 */
@Slf4j
@Component("autoCreateTicketJobB")
public class AutoCreateTicketJobB implements JobHandler {

    @Resource
    private JobMapper jobMapper;

    @Resource
    private TicketMapper ticketMapper;

    @Resource
    private AdminUserMapper adminUserMapper;

    @Resource
    private TicketLogMapper ticketLogMapper;

    @Resource
    private WebProperties webProperties;

    @Resource
    private NotifyMessageSendApiImpl notifyMessageSendApi;

    @Resource
    private SiteService siteService;



    @Override
    @TenantIgnore
    public String execute(String param) {
        System.out.println("自动创建保养工单-----------------------------------"+LocalDateTime.now());

        if(param != null && !param.isEmpty()){
            JobDO jobDO = jobMapper.selectById(Long.parseLong(param));
            if(jobDO != null){
                ReentrantLock reentrantLock = new ReentrantLock();
                try {
                Integer ticketType = 2;//保养
                String inspectionItem = jobDO.getInspectionItem();//检查项
                Long operatorId = jobDO.getOperatorId();//指派人
                Integer timeoutHour = jobDO.getTimeoutHour();
                String operatorName = "";
                Long tenantId = 0L;
                Long deptId = 0L;
                AdminUserDO adminUserDO = adminUserMapper.selectById(operatorId);
                if(adminUserDO != null){
                    operatorName = adminUserDO.getNickname();
                    tenantId = adminUserDO.getTenantId();
                    deptId= adminUserDO.getDeptId();
                }else {
                    return "暂无该指派人";
                }

                String siteIds = jobDO.getSiteIds();
                String[] siteIdsSplit = siteIds.split(",");
                Long areaId = jobDO.getAreaId();


                long l = ticketMapper.selectCount(new LambdaQueryWrapper<TicketDO>().apply("DATE(create_time) = CURDATE()"));

                // 1. 提取固定值到循环外部
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
                String format = LocalDate.now().format(formatter); // 日期前缀只计算一次
                String ticketDesc = "系统自动创建工单"; // 固定描述
                int ticketLevel = 1; // 固定优先级
                Integer ticketStatus = TicketStatusEnum.PENDING.getCode(); // 固定状态



                // 2. 预计算总工单数量，预分配 List 容量
                int totalTickets = jobDO.getSiteIds().split(",").length;
                List<TicketDO> insertList = new ArrayList<>(totalTickets);
                List<TicketLogDO> insertLogList = new ArrayList<>(totalTickets);

                // 3. 工单编号优化：预生成前缀 + 高效计数器
                AtomicLong counter = new AtomicLong(l); // 线程安全计数器
                String numberPrefix = "WO-" + format + "-";

                for (String s1 : siteIdsSplit) {
                    TicketDO ticketDO = new TicketDO();
                    ticketDO.setTicketType(ticketType); //工单类型 保养
                    ticketDO.setTicketStatus(ticketStatus); //待处理
                    ticketDO.setAreaId(areaId);//区域
                    ticketDO.setSiteId(Long.parseLong(s1));//电站
                    ticketDO.setTicketLevel(ticketLevel); //默认低优先级
                    ticketDO.setTicketDesc(ticketDesc);//工单描述
                    ticketDO.setInspectionItem(inspectionItem);//检查项
                    ticketDO.setOperatorId(operatorId); //指派人
                    ticketDO.setDeptId(deptId);
                    ticketDO.setTenantId(tenantId);
                    ticketDO.setTimeoutHour(timeoutHour);
                    ticketDO.setThirdId(2);
                    // 工单编号生成优化：StringBuilder 替代格式化
                    long seq = counter.incrementAndGet();
                    String ticketNumber = new StringBuilder(numberPrefix)
                            .append(String.format("%05d", seq))
                            .toString();
                    ticketDO.setTicketNumber(ticketNumber);
                    insertList.add(ticketDO);
                }

                if(!insertList.isEmpty()){
                    ticketMapper.insertBatch(insertList);
                    for (TicketDO ticketDO : insertList) {
                        //插入日志
                        TicketLogDO ticketLogDO = new TicketLogDO();
                        ticketLogDO.setTicketId(ticketDO.getId());
                        ticketLogDO.setContent(String.format(TicketLogRecordConstants.CREATE_TICKET,"系统定时 ",operatorName));
                        ticketLogDO.setTenantId(tenantId);
                        insertLogList.add(ticketLogDO);
                        ticketLogDO.setTenantId(tenantId);
                    }
                    if(!insertLogList.isEmpty()){
                        ticketLogMapper.insertBatch(insertLogList);
                    }
                    // 发送站内信
                    Map<String, Object> templateParams = new HashMap<>();
                    templateParams.put("siteNames", siteService.getNames(siteIds));
                    templateParams.put("url", webProperties.getAdminUi().getUrl() + "/#/order/my");


                    NotifySendSingleToUserReqDTO notifySendSingleToUserReqDTO = new NotifySendSingleToUserReqDTO();
                    notifySendSingleToUserReqDTO.setUserId(operatorId);
                    notifySendSingleToUserReqDTO.setTemplateCode(YmMessageEnum.TIMING_TICKET_NOTICE.getSmsTemplateCode());
                    notifySendSingleToUserReqDTO.setTemplateParams(templateParams);
                    notifySendSingleToUserReqDTO.setTenantId(tenantId);
                    notifyMessageSendApi.sendSingleMessageToAdminTenant(notifySendSingleToUserReqDTO);
                    return String.format("定时创建巡检工单数量 %s 个",insertList.size());
                }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    reentrantLock.unlock();
                }
            }
        }
        return "未创建定时工单";
    }
}
